home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
vtkerma1.arc
/
MSRECV.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-02-13
|
31KB
|
1,106 lines
PAGE 59, 132
TITLE MSRECV -- Module to Receive a file
; Update 13 Jan 86
IF1
%OUT >> Starting pass 1
ELSE
%OUT >> Starting pass 2
ENDIF
PUBLIC Read1, Read2, rin21, rfile3, read, updrtr, nak, rrinit
INCLUDE MsDefs.H
DataS SEGMENT PUBLIC 'DataS'
EXTRN fcb:byte, data:byte, bufpnt:word, chrcnt:word, curchk:byte
EXTRN comand:byte, flags:byte, pack:byte, trans:byte, OFilSz:WORD
ermes7 DB 'Unable to Receive Initiate$'
ermes8 DB 'Unable to receive file name$'
ermes9 DB 'Unable to receive end of file$'
erms10 DB 'Unable to receive data$'
erms11 DB 'Unable to receive attribute or data$'
erms12 DB 'Not enough room on disk for file$'
ermes7a DB 'Remote '
Program_name
DB ': Unable to receive initiate$'
ermes8a DB 'Remote '
Program_name
DB ': Unable to receive file name$'
ermes9a DB 'Remote '
Program_name
DB ': Unable to receive end of file$'
erms10a DB 'Remote '
Program_name
DB ': Unable to receive data$'
erms11a DB 'Remote '
Program_name
DB ': Unable to receive attribute or data$'
erms12a DB 'Remote '
Program_name
DB ': Not enough room on disk for file$'
infms1 DB cr,' Receiving: In progress$'
infms3 DB 'Completed$'
infms4 DB 'Failed$'
infms6 DB 'Interrupted$'
infms7 DB cr,' Percent transferred: 100%$'
filhlp2 DB ' Confirm with carriage return, or specify name '
DB 'to use for incoming file$'
crlf DB cr,lf,'$'
temp dw 0
ATR_KBytes DW 0 ; File size in K, according to file's sender
ATR_Avail DW 0 ; Free space on disk, in K
ATR_Ptr DW 0 ; Ptr to reading point in attribute string
ATR_End_ptr DW 0 ; Ptr to point we don't read from
ATR_Length DW 0 ; Number of chars in attribute data subfield
ATR_Attribute DB 0 ; ASCII char representing attribute type
SPC_Msg1 DB 'The incoming file requires $'
SPC_Msg2 DB ' K bytes of disk space, but$'
SPC_Msg3 DB 'the disk you are using has only $'
SPC_Msg4 DB ' K bytes available.$'
SPC_Msg5 DB 'Please insert a formatted disk which'
DB ' has enough room for this file.$'
SPC_Msg7 DB 'Type control-C to ABORT, any other key to try a new disk.$'
SPC_Addr1 EQU (15*256)+5 ; Locations for messages
SPC_Addr3 EQU (16*256)+5
SPC_Addr5 EQU (18*256)+5
SPC_Addr7 EQU (20*256)+5
datas ends
Code SEGMENT PUBLIC
EXTRN gofil:near, outbuf:near, fixfcb:near, comnd:near, EOT_bells:NEAR
EXTRN spack:near, rpack:near, serini:NEAR, Nout:NEAR, poscur:near
EXTRN spar:near, rpar:near, init:near, init1:near, cxmsg:near
EXTRN error:near, ptchr:near, PerPos:near, ClearL:near
EXTRN dodec:near, doenc:near, errpack:near, beep:near
EXTRN ClrMod:near, Close_transfer_screen:NEAR, Show_packets:NEAR
EXTRN Show_error:NEAR, Show_status:NEAR, Show_retries:NEAR
EXTRN Clear_percent_message:NEAR
ASSUME cs:Code, ds:DataS
; Update retry count and fall through to send a NAK
nak0: call updrtr ; Update retry count
nak: mov ax,pack.pktnum ; Get the packet number we're waiting for
mov pack.argblk,ax
mov pack.argbk1,0
mov cx,0 ; No data, but this may change
call doenc ; So call encode
mov ah,'N' ; NAK that packet
call Spack
jmp Abort
ret
updrtr: cmp pack.state,'A' ; Supposed to abort?
je upd0 ; Yes, don't bother with retry count
inc pack.numrtr ; Increment the number of retries
cmp flags.xflg,1 ; Writing to screen?
je upd0
call Show_retries ; Use common routine
upd0: ret
; init variables for read..
rrinit proc near
mov pack.numpkt,0 ; Set the number of packets to zero
mov pack.numrtr,0 ; Set the number of retries to zero
mov pack.pktnum,0 ; Set the packet number to zero
mov pack.numtry,0 ; Set the number of tries to zero
ret
rrinit endp
; RECEIVE command -- Some code moved to the GET routine. [21a]
READ PROC NEAR
mov comand.cmrflg,1 ; Say we're receiving a file. [21a start]
mov comand.cmcr,1 ; Allow bare CR after RECEIVE
mov flags.droflg,0 ; Override default drive flag
mov flags.nmoflg,0 ; Override file name from other host?
mov dx,offset fcb ; Put filename here.
mov bx,offset filhlp2 ; Text of help message
mov ah,cmifi ; Read in the filename
call comnd
jmp RSkp
mov comand.cmrflg,0 ; Reset flag
mov comand.cmcr,0
mov flags.wldflg,0 ; Just in case
mov ah,cmcfm ; Get a confirm
call comnd
jmp r
mov pack.state,'R' ; Set the state to receive initiate
call Init ; Clear the screen, put up FT screen
call rrinit ; init variables for read
call serini ; Initialize serial port. [14]
call Read1 ; Call our routine to do the receive
nop ; He skips usually
nop
nop
jmp RSkp ; Return skip to main KERMIT loop
; Routine to perform a RECEIVE of a file (called from here and from MSSERV)
Read1: mov flags.cxzflg,0 ; Reset ^X/^Z flag. [20c]
call init1 ; Clear the line and initialize the buffers
mov dx, OFFSET infms1 ; "Receiving: In progress"
call Show_status ; Display status
call Show_packets ; Display packet count
call ClearL ; Make sure display looks right
call Show_retries ; and number of retries
call ClearL ; Likewise
read2: cmp flags.xflg,1 ; Are we receiving to the screen. [21c]
je read21 ; Skip the screen stuff. [21c]
call Show_packets ; Display the packet count
read21: mov ah,pack.state ; Get the state. [21c]
cmp ah,'T' ; Are we in the aTtribute state?
jne read23
call RAttr ; Waiting for attribute packet or data
jmp read2
read23: cmp ah,'D' ; Are we in the Data receive state?
jne read3
call rdata
jmp read2
read3: cmp ah,'F' ; Are we in the file receive state?
jne read4
call rfile ; Call receive file
jmp read2
read4: cmp ah,'R' ; Are we in the receive initiate state?
jne read5
call rinit
jmp read2
Read5: cmp ah,'C' ; Are we in the receive complete state?
jne read6
cmp flags.xflg,0 ; Did we write to the screen? [21c]
je Read5a ; No so print status. [21c]
mov Flags.xflg, 0 ; Reset it. [21c]
jmp RSkp ; Yes, so just return. [21c]
Read5a: cmp Flags.RemFlg,0 ; Remote mode?
jne Read7a ; Yes, don't type anything
cmp Flags.cxzflg, 0 ; completed normally?
jne Read5b ; no, don't bother with this
call PerPos ; Note that we are now 100% done
mov ah, PrStr
mov dx, OFFSET infms7
int Dos
mov dx, OFFSET InfMs3 ; Message saying success
jmp SHORT Read5c
Read5b: mov dx, OFFSET infms6 ; Say was interrupted
Read5c: call Show_status ; Display the message, whatever it is
call EOT_bells ; Make optional noise
jmp SHORT Read7
; Here, we have some type of error -- clean up and go home
read6: cmp flags.xflg,0 ; Did we write out to screen? [21c]
je read61 ; No so print status. [21c]
mov flags.xflg,0 ; Reset it. [21c]
jmp rskp ; Print onto screen. [21c]
read61: mov dx,offset infms4 ; Plus a little cuteness
call Show_status
read7: call Close_transfer_screen ; Clean up for command mode
read7a: jmp rskp
READ ENDP
; Receive routines
; Receive init
RINIT PROC NEAR
mov ah,pack.numtry ; Get the number of tries
cmp ah,imxtry ; Have we reached the maximum number of tries?
jl rinit2
mov dx,offset ermes7
call Show_error ; Display message
mov bx,offset ermes7a
call errpack ; Send error packet just in case
jmp abort ; Change the state to abort
rinit2: inc ah ; Increment it
mov pack.numtry,ah ; Save the updated number of tries
mov ax,pack.argbk2 ; get packet type if here from get
cmp flags.getflg,1 ; Have we already read in the packet? [21a]
je rin21a ; Yes, so don't call RPACK. [21a]
mov ah,trans.chklen
mov curchk,ah ; Save checksum length we want to use
mov trans.chklen,1 ; Use 1 char for init packet
call rpack ; Get a packet
jmp rin22 ; Trashed packet: nak, retry
push ax
mov ah,curchk
mov trans.chklen,ah ; Reset to desired value
pop ax
rin21a: cmp ah,'S' ; Is it a send initiate packet?
jne rinit3 ; If not see if its an error
rin21: mov flags.getflg,0 ; Reset flag. [21a]
mov ah,pack.numtry ; Get the number of tries
mov pack.oldtry,ah ; Save it
mov pack.numtry,0 ; Reset the number of tries
mov ax,pack.argblk ; Returned packet number. (Synchronize them.)
inc ax ; Increment it
and ax,3FH ; Turn off the two high order bits
mov pack.pktnum,ax ; Save modulo 64 of the number
mov bx,pack.numpkt
inc bx ; Increment the number of packets
mov pack.numpkt,bx
mov ax,pack.argbk1 ; Get the number of arguments received
mov bx,offset data ; Get a pointer to the data
call spar ; Get the data into the proper variables
mov bx,offset data ; Get a pointer to our data block
call rpar ; Set up the receive parameters
xchg ah,al
mov ah,0
mov pack.argbk1,ax ; Store the returned number of arguments
mov ah,trans.chklen ; Checksum length we'll use
mov curchk,ah ; Save it
mov trans.chklen,1 ; Use 1 char for init packet
mov ah,'Y' ; Acknowledge packet
call spack ; Send the packet
jmp abort
mov ah,curchk ; Checksum length we'll use
mov trans.chklen,ah ; Reset to desired value
mov ah,'F' ; Set the state to file send
mov pack.state,ah
ret
rin22: mov ah,curchk
mov trans.chklen,ah ; Reset to desired value
jmp nak0 ; Try again
rinit3: cmp ah,'E' ; Is it an error packet?
jne rinit4
call error
rinit4: jmp abort
RINIT ENDP
; Receive file
RFILE PROC NEAR
cmp pack.numtry,maxtry ; Have we reached the maximum number of tries?
jl rfile1
mov dx,offset ermes8
call Show_error ; Display message
mov bx,offset ermes8a
call errpack ; Send error packet just in case
jmp abort ; Change the state to abort
rfile1: inc pack.numtry ; Save the updated number of tries
call rpack ; Get a packet
jmp nak0 ; Trashed packet: nak, retry
cmp ah,'S' ; Is it a send initiate packet?
je rfil10
call dodec ; Decode all incoming packets
jmp rfile2 ; No, try next type
rfil10: cmp pack.oldtry,imxtry ; Have we reached the maximum number of tries?
jl rfil12 ; If not proceed
mov dx,offset ermes7
call Show_error ; Display message
mov bx,offset ermes7a
call errpack ; Send error packet just in case
jmp abort ; Change the state to abort
%OUT >> About half way through source file
rfil12: inc pack.oldtry ; Save the updated number of tries
mov ax,pack.pktnum ; Get the present packet number
cmp ax,0 ; Had we wrapped around? [18 start]
jne rfilx
mov ax,64
rfilx: dec ax ; Decrement. [18 end -- new label]
cmp ax,pack.argblk ; Is the packet's number one less than now?
je rfil13
jmp nak0 ; No, NAK and try again
rfil13: call updrtr ; Update retry count
mov pack.numtry,0 ; Reset the number of tries
mov bx,offset data ; Get a pointer to our data block
call rpar ; Set up the parameter information
xchg ah,al
mov ah,0
mov pack.argbk1,ax ; Save the number of arguments
mov ah,'Y' ; Acknowledge packet
call spack ; Send the packet
jmp abort
ret
rfile2: cmp ah,'Z' ; Is it an EOF packet?
jne rfile3 ; No, try next type
cmp pack.oldtry,maxtry ; Have we reached the maximum number of tries?
jl rfil21 ; If not proceed
mov dx,offset ermes9
call Show_error ; DIsplay message
mov bx,offset ermes9a
call errpack ; Send error packet just in case
jmp abort ; Change the state to abort
rfil21: inc pack.oldtry ; Increment it
mov ax,pack.pktnum ; Get the present packet number
cmp ax,0 ; Had we wrapped around? [18 start]
jne rfily
mov ax,64
rfily: dec ax ; Decrement. [18 end -- new label]
cmp ax,pack.argblk ; Is the packet's number one less than now?
je rfil24
jmp nak0 ; No, NAK and try again
rfil24: call updrtr ; Update retry count
mov pack.numtry,0
mov pack.argbk1,0 ; No data. (The packet number is in argblk.)
mov cx,0
call doenc
mov ah,'Y' ; Acknowledge packet
call spack ; Send the packet
jmp abort
ret
rfile3: cmp ah,'F' ; Start of file?
je rfil31 ; Yes. [21c]
cmp ah,'X' ; Text header packet? [21c]
jne rfile4 ; Neither one.
rfil31: mov ax,pack.argblk ; Get the packet number. [21c]
cmp ax,pack.pktnum ; Is it the right packet number?
je rfil32
jmp nak ; No, NAK it and try again
rfil32: inc ax ; Increment the packet number
and ax,3FH ; Turn off the two high order bits
mov pack.pktnum,ax ; Save modulo 64 of the number
inc pack.numpkt ; Increment the number of packets
call gofil ; Get a file to write to
jmp abort
call init1 ; Initialize all the buffers
mov ah,pack.numtry ; Get the number of tries
mov pack.oldtry,ah ; Save it
mov pack.numtry,0 ; Reset the number of tries
mov pack.argbk1,0 ; No data. (The packet number is in argblk.)
call Clear_percent_message ; Erase this for now
mov cx,0
call doenc
mov ah,'Y' ; Acknowledge packet
call spack ; Send the packet
jmp abort
; mov pack.state,'D'
mov pack.state,'T' ; Set the state to waiting for aTtribute
ret
rfile4: cmp ah,'B' ; End of transmission
jne rfile5
mov ax,pack.pktnum
cmp ax,pack.argblk ; Do we match?
je rfil41
jmp nak ; No, NAK it and try again
rfil41: mov pack.argbk1,0 ; No data. (Packet number already in argblk)
mov cx,0
call doenc
mov ah,'Y' ; Acknowledge packet
call spack ; Send the packet
jmp abort
mov pack.state,'C' ; Set the state to complete
ret
rfile5: cmp ah,'E' ; Is it an error packet
jne rfile6
call error
rfile6: jmp abort
RFILE ENDP
; Receive attribute or data
PUBLIC RAttr, rdat11, ATR_2, ATR_3, ATR_5, ATR_err
RAttr PROC
cmp pack.numtry,maxtry ; Get the number of tries
jae ATR_err ; Too many errors, go blow up
inc pack.numtry ; Save the updated number of tries
call rpack ; Get a packet
jmp nak0 ; Trashed packet: nak, retry
cmp ah,'D' ; Is it a data packet?
jne ATR_2 ; No, see if it is an Attribute packet
; Deal with Data (D) packet
mov pack.state, 'D' ; Switch to Data state
jmp rdat11 ; Go join the RDATA routine
ATR_2: cmp ah, 'A' ; Attribute packet?
je ATR_3 ; Yes
jmp rdata2 ; No, use RDATA code to see what it is
; Deal with Attribute (A) packet
ATR_3: mov ax,pack.pktnum ; Get the present packet number
cmp ax,pack.argblk ; Is the packet's number correct?
je ATR_7 ; Yes
; Got the wrong packet number
cmp pack.oldtry,maxtry ; Have we reached the maximum number of tries?
jae ATR_err ; Too many errors
inc pack.oldtry ; Save the updated number of tries
mov ax,pack.pktnum
cmp ax,0 ; Had we wrapped around? [18 start]
jne ATR_5
mov ax,64
ATR_5: dec ax ; [14] [18 end -- new label]
cmp ax,pack.argblk ; Is the packet's number one less than now?
je ATR_6 ; Yes
jmp nak0 ; No, NAK it and try again
; File sender has sent us a second copy of a packet we already ACKed,
; which suggests that our ACK was lost. Send another ACK so we can move
; on to the next packet. This constitutes a retry
ATR_6: call updrtr ; Update retry count
mov pack.numtry,0 ; Reset number of tries
mov pack.argbk1,0 ; No data. (The packet number is in argblk.)
mov cx,0
call doenc
mov ah,'Y' ; Acknowledge packet
call spack ; Send the packet
jmp abort
ret
; Common point for error, Too many retries
ATR_err:
mov dx,offset erms11
call Show_error ; Display message
mov bx,offset erms11a
call errpack ; Send error packet just in case
jmp abort ; Change the state to abort
PUBLIC ATR_7, ATR_8, ATR_9, ATR_10, ATR_LP1, ATR_Ignore
PUBLIC ATR_Do_filesize
; Have good Attribute packet, the right packet number and everything
ATR_7: inc ax ; Increment the packet number
and ax,3FH ; Turn off the two high order bits
mov pack.pktnum,ax ; Save modulo 64 of the number
inc pack.numpkt ; Increment the number of packets
mov ah,pack.numtry ; Get the number of tries
mov pack.oldtry,ah ; Save it
; Interrupted?
mov ax,pack.argbk1 ; Get the length of the data
cmp flags.cxzflg,0 ; Has the user typed a ^X or ^Z? [20c]
je ATR_8 ; No, keep dealing with Attribute packet
cmp flags.abfflg,1 ; Discard incomplete files?
je ATR_9 ; If yes don't write data out to file
; Process the attribute(s) in the packet
ATR_8: mov ax, OFFSET data ; Where the data comes from
mov ATR_Ptr, ax ; Store for reading of attributes strings
add ax, pack.argbk1 ; Add in the length of the data
mov ATR_End_ptr, ax ; Store the ending pointer
ATR_LP1:
call ATR_Get_attribute ; Get the attribute
jc ATR_9 ; End of file
; Determine attribute type
cmp ATR_Attribute, "!" ; Is the attribute the one for file size?
je ATR_Do_filesize ; Yes, go handle it
ATR_Ignore:
mov ax, ATR_Length ; Get the attr length
add ATR_Ptr, ax ; Advance the pointer
jmp ATR_LP1 ; Go try for another attribute
; Type is "file size in K bytes"
ATR_Do_filesize:
mov cx, ATR_Length ; Load up number of expected digits
call ATR_Get_number ; Get the file size
jc ATR_9 ; EOF or non-numeric junk
mov ATR_KBytes, ax ; Save file size in K bytes
mov dx, ax ; Copy file size in K to dx
mov cl, 6 ; This many bits
shr dx, cl ; Get high order 10 bits from ax into low
; order position in dx
mov cl, 10 ; This many bits
shl ax, cl ; Get low order 6 bits from ax into high
; order position in ax
mov bx, 100 ; Get a 100 (base of percentage) into bx
div bx ; Convert doubleword byte count into percent-
; adjusted value for PerPr routine
mov OFilSz, ax ; Store it away for later
; Jump here after user has inserted a new disk
ATR_Try_again:
call ATR_Get_disk_freespace ; See how much space is left on the disk
mov ATR_Avail, ax ; Store the answer for possible later display
cmp ax, ATR_KBytes ; Enough room for the file?
jae ATR_LP1 ; There is enough room, read any other
; attributes we find
mov ah, ClosF ; Close the file
mov dx, OFFSET Fcb
int Dos
mov ah, DelF ; Delete it
int Dos
call ATR_Show_space_problem ; Inform the user, ask for a new disk
mov ah, ConInQ ; Quiet console input
int Dos ; Wait until user hits a key
cmp al, 3 ; Control-C?
je ATR_Abort ; Yes, don't accept the file
call ATR_Make_new_file ; Create the file on the new disk (blow old
; file away if it already exists)
call ATR_Fix_screen ; Get rid of the message
jmp ATR_Try_again ; Go try again
ATR_9: mov pack.numtry,0 ; Reset the number of tries
mov pack.argbk1,0 ; No data. (Packet number still in argblk.)
sub cx, cx ; Make a zero
cmp flags.cxzflg,0 ; Interrupt file transfer? [20c]
je ATR_10 ; Nope. [20c]
mov bx,offset data ; Send data in ACK in case remote... [20c]
mov ah,flags.cxzflg ; ... knows about ^X/^Z. [20c]
mov [bx],ah ; Put data into the packet. [20c]
mov pack.argbk1,1 ; Set data size to 1. [20c]
mov cx,1
; Successful receipt of an Attribute packet, ACK the packet
ATR_10: call doenc
mov ah,'Y' ; Acknowledge packet
call spack
jmp abort
ret ; Done here
; Routines used to handle attribute packets
PUBLIC ATR_Get_attribute, ATR_Exit_error, ATR_Exit, ATR_Abort
PUBLIC ATR_Get_a_char, ATR_Get_number, ATR_Get_disk_freespace
PUBLIC ATR_Show_space_problem
ATR_Get_attribute:
call ATR_Get_a_char ; Get the attribute character
jc ATR_Exit ; End of file
mov ATR_Attribute, al ; Store it
call ATR_Get_a_char ; Get the number of digits in the file size
jc ATR_Exit ; End of file
sub al, 32 ; Convert to true number
cbw ; Zero ah
mov ATR_Length, ax ; Store the data length
; Make sure that this is a valid length
mov ax, ATR_End_ptr ; Get ending ptr
sub ax, ATR_Ptr ; Get length until end-of-data
cmp ax, ATR_Length ; Is size sufficient for this data subfield?
jl ATR_Exit_error ; No, bomb it
clc ; No error
ret ; Return
ATR_Exit_error:
stc ; Force error flag
ATR_Exit:
ret ; Return
ATR_Abort:
mov dx,offset erms12
call Show_error ; Display message
mov bx,offset erms12a
call errpack ; Send error packet just in case
jmp abort ; Change the state to abort
ATR_Get_a_char:
; Returns ...
; Carry set = No char to be found
; al/ the character, if any
push si ; Save reg
mov si, ATR_Ptr ; Our reading ptr
cmp si, ATR_End_ptr ; Pointing at end-of-data, or higher?
jb ATR_GCh_1 ; No, no error
stc ; Flag the error
jmp SHORT ATR_GCh_2 ; Finish up
ATR_GCh_1:
cld ; Forwards
lodsb ; Pick up the new character
mov ATR_Ptr, si ; Save updated ptr
clc ; No error
ATR_GCh_2:
pop si ; Restore reg
ret ; Done here
ATR_Get_number:
; Call with ...
; cx/ number of digits to read
;
; Returns ...
; Carry set = No number
; ax/ the number, if any
sub bx, bx ; Clear a working register
PN_1: call ATR_Get_a_char ; Get a char
jc ATR_Badnum ; None to be got
cmp al, '0' ; Lower than 0?
jb ATR_Badnum ; Yes, done here
cmp al, '9' ; Higher than 9?
ja ATR_Badnum ; Yes, done here
sub al, '0' ; Make ASCII digit into decimal
sub ah, ah ; Clear ah
xchg ax, bx ; Swap ax and bx
mov dx, 10 ; Get a ten
mul dx ; Multiply old number by ten
add bx, ax ; Add in the new digit
loop PN_1 ; Go get another char, if more to do
clc ; We have a number
mov ax, bx ; Copy over the number
ret ; Done here
ATR_Badnum:
stc ; No number
ret ; Go home
; See how much space is available on the connected disk, returns with ...
; ax/ Number of Kilobytes (1024) available on "default" disk
ATR_Get_disk_freespace:
sub dl, dl ; Want data for the default drive
mov ah, 36h ; DOS function call for space available
int DOS ; Do it .
cmp ax, 0ffffh ; Invalid drive spec?
je ATR_DSK_Problem ; There is some problem
; At this point, we have the following ...
; ax/ number of sectors per cluster
; bx/ number of free clusters
; cx/ number of bytes per sector
mul cx ; ax * cx --> ax, number of bytes per cluster
mov cl, 9 ; Want to shift right this many bits
shr ax, cl ; Divide by 512, so final result will fit in ax
mul bx ; ax * bx --> ax, (number of bytes free)/512
shr ax, 1 ; Divide by 2 to convert this to Kilobytes
ret ; Done here
ATR_DSK_Problem:
sub ax, ax ; Pretend no disk space free
ret ; Done here
ATR_Show_space_problem:
Tmsg MACRO Message
mov dx, OFFSET Message
mov ah, PrStr
int Dos
ENDM
GoMsg MACRO Number
mov dx, SPC_Addr&Number
call PosCur
Tmsg SPC_Msg&Number
ENDM
GoMsg 1
mov ax, ATR_KBytes
call Nout
Tmsg SPC_Msg2
GoMsg 3
mov ax, ATR_Avail
call Nout
Tmsg SPC_Msg4
GoMsg 5
GoMsg 7
jmp Beep ; Go make a noise, ret from there
ATR_Make_new_file:
mov ah, DelF ; Delete the file if it exists
mov dx, OFFSET Fcb
int Dos
mov ah, MakeF ; Now create it
int Dos
ret
ATR_Fix_screen:
Clear_it MACRO Address
mov dx, Address ;; Position
call PosCur ;; Go there
call ClearL ;; Clear out any existing message
ENDM
Clear_it SPC_Addr1 ; Clear each line
Clear_it SPC_Addr3
Clear_it SPC_Addr5
Clear_it SPC_Addr7
ret
RAttr ENDP
; Receive data
RDATA PROC
cmp pack.numtry,maxtry ; Get the number of tries
jl rdata1
mov dx,offset erms10
call Show_error ; Display message
mov bx,offset erms10a
call errpack ; Send error packet just in case
jmp abort ; Change the state to abort
rdata1: inc pack.numtry ; Save the updated number of tries
call rpack ; Get a packet
jmp Nak0 ; Trashed packet: nak, retry
cmp ah,'D' ; Is it a data packet?
je rdat11
call dodec ; Decode data
jmp rdata2 ; No, try next type
rdat11: mov ax,pack.pktnum ; Get the present packet number
cmp ax,pack.argblk ; Is the packet's number correct?
jz rdat14
cmp pack.oldtry,maxtry ; Have we reached the maximum number of tries?
jl rdat12 ; If not proceed
mov dx,offset erms10
call Show_error ; Display message
mov bx,offset erms10a
call errpack ; Send error packet just in case
jmp abort ; Change the state to abort
rdat12: inc pack.oldtry ; Save the updated number of tries
mov ax,pack.pktnum
cmp ax,0 ; Had we wrapped around? [18 start]
jne rdatx
mov ax,64
rdatx: dec ax ; [14] [18 end -- new label]
cmp ax,pack.argblk ; Is the packet's number one less than now?
je rdat13
jmp nak0 ; No, NAK it and try again
rdat13: call updrtr ; Update retry count
mov pack.numtry,0 ; Reset number of tries
mov pack.argbk1,0 ; No data. (The packet number is in argblk.)
mov cx,0
call doenc
mov ah,'Y' ; Acknowledge packet
call spack ; Send the packet
jmp Abort
ret
rdat14: inc ax ; Increment the packet number
and ax,3FH ; Turn off the two high order bits
mov pack.pktnum,ax ; Save modulo 64 of the number
inc pack.numpkt ; Increment the number of packets
mov ah,pack.numtry ; Get the number of tries
mov pack.oldtry,ah ; Save it
mov ax,pack.argbk1 ; Get the length of the data
cmp flags.cxzflg,0 ; Has the user typed a ^X or ^Z? [20c]
je rdt14x ; No, write out the data
cmp flags.abfflg,1 ; Discard incomplete files?
je rdat15 ; If yes don't write data out to file. [20c]
rdt14x: mov bx,offset data ; Where the data is. [25]
call ptchr
jmp Abort ; Unable to write out chars
rdat15: mov pack.numtry,0 ; Reset the number of tries
mov pack.argbk1,0 ; No data. (Packet number still in argblk.)
mov cx,0
cmp flags.cxzflg,0 ; Interrupt file transfer? [20c]
je rdat16 ; Nope. [20c]
mov bx,offset data ; Send data in ACK in case remote... [20c]
mov ah,flags.cxzflg ; ... knows about ^X/^Z. [20c]
mov [bx],ah ; Put data into the packet. [20c]
mov pack.argbk1,1 ; Set data size to 1. [20c]
mov cx,1
rdat16: call doenc
mov ah,'Y' ; Acknowledge packet
call spack ; Send the packet
jmp Abort
ret
rdata2: cmp ah,'F' ; Start of file?
je rdat20 ; Yup. [21c]
cmp ah,'X' ; Text header packet? [21c]
jne rdata3 ; No, try next type
rdat20: cmp pack.oldtry,maxtry ; Reached the max number of tries? [21c]
jl rdat21 ; If not proceed
mov dx,offset ermes8
call Show_error ; Display message
mov bx,offset ermes8a
call errpack ; Send error packet just in case
jmp abort ; Change the state to abort
rdat21: inc pack.oldtry ; Save the updated number of tries
mov ax,pack.pktnum
cmp ax,0 ; Had we wrapped around? [18 start]
jne rdaty
mov ax,64
rdaty: dec ax ; [14 Omitted accidentally - D.T.] [18 end]
cmp ax,pack.argblk ; Is the packet's number one less than now?
je rdat22
jmp nak0 ; No, NAK it and try again
rdat22: call updrtr ; Update retry count
mov pack.numtry,0 ; Reset number of tries
mov pack.argbk1,0 ; No data. (The packet number is in argblk.)
mov cx,0
call doenc
mov ah,'Y' ; Acknowledge packet
call spack ; Send the packet
jmp Abort
ret
rdata3: cmp ah,'Z' ; Is it a EOF packet?
je rdat3x ; [13]
jmp rdata4 ; Try and see if its an error. [13]
rdat3x: mov ax,pack.pktnum ; Get the present packet number. [13]
cmp ax,pack.argblk ; Is the packet's number correct?
je rdat32
jmp nak0 ; No, NAK it and try again
rdat32: inc ax ; Increment the packet number
and ax,3FH ; Turn off the two high order bits
mov pack.pktnum,ax ; Save modulo 64 of the number
inc pack.numpkt
cmp flags.cxzflg,0 ; Do we want to discard the file? [20c]
jne rdt32x ; Yes. [20c]
cmp pack.argbk1,1 ; One piece of data? [20c]
jne rdat33 ; Nope - finish writing out file? [20c]
mov bx,offset data ; Get data area. [20c]
mov ah,[bx] ; Get the data. [20c]
cmp ah,'D' ; "D" for discard? [20c]
jne rdat33 ; Nope - write out file. [20c]
rdt32x: cmp flags.abfflg,0 ; Keep incomplete files?
je rdat33 ; Yes, go write it out
PUBLIC MSRECV_close_file_1
MSRECV_close_file_1:
mov ah,closf ; First, close the file
mov dx,offset fcb ; Give the file parameters. [20c]
int dos ; Kill it, ignore errors. [20c]
mov ah,delf ; Delete the file if opened. [20c]
int dos
cmp flags.cxzflg,'X' ; Kill one file or all? [20c]
jne rdat36 ; No so leave flag alone. [20c]
call cxmsg ; Clear msg about interrupt. [20c]
mov flags.cxzflg,0 ; Reset - ^X only kills one file. [20c]
jmp rdat36
PUBLIC rdat33
rdat33: mov bx,bufpnt ; Get the dma pointer
mov ax,80H
sub ax,chrcnt ; Get the number of chars left in the DMA
cmp flags.eofcz,0 ; should we write a ^Z?
jz rdat35 ; no, keep going
cmp flags.xflg,0 ; writing to a file?
jne rdat35 ; no, skip ^Z
cmp ax,80H ; [13 start]
jne rdat34
call outbuf ; Write out buffer if no room for ^Z
jmp abort
mov ax,0 ; [13 end]
inc chrcnt ; Increment size by one (not two). [21b]
rdat34: mov cl,'Z'-100O ; Put in a ^Z for EOF
mov [bx],cl ; Add it. [21c]
inc ax
dec chrcnt
rdat35: mov cx,chrcnt
mov temp,cx
call outbuf ; Output the last buffer
jmp abort ; Give up if the disk is full
mov ax,temp ; Prepare for the function call
call fixfcb
cmp Flags.XFlg, 0 ; Writing to screen?
je MSRECV_close_file_2 ; No, go close the file
mov ah, PrStr ; Code to write to screen
mov dx, OFFSET CrLf ; A CrLf
int Dos ; Type it
mov ah, PrStr ; Code to write to screen
mov dx, OFFSET CrLf ; A CrLf
int Dos ; Type another CrLf
jmp SHORT rdat37 ; Skip over this code
PUBLIC MSRECV_close_file_2
MSRECV_close_file_2:
mov ah,closf ; Close up the file
mov dx,offset fcb
int dos
rdat36: cmp flags.destflg,1 ; Writing to disk?
je rdat37 ; Yes, skip next part
cmp flags.xflg,1 ; Writing to screen?
je rdat37 ; Yes, skip this part
mov dl,ff ; Send a form feed
mov ah,lstout ; Write out to first printer
int dos
rdat37: mov ah,pack.numtry ; Get the number of tries
mov pack.oldtry,ah ; Save it
mov pack.numtry,0 ; Reset the number of tries
mov pack.argbk1,0 ; No data. (The packet number is in argblk.)
mov cx,0
call doenc
mov ah,'Y' ; Acknowledge packet
call spack ; Send the packet
jmp abort
mov pack.state,'F'
ret
rdata4: cmp ah,'E' ; Is it an error packet
jne rdata5
call error
rdata5: jmp abort
RDATA ENDP
ABORT PROC
mov pack.state,'A' ; Otherwise abort
ret
ABORT ENDP
; Jumping to this location is like retskp. It assumes the instruction
; after the call is a jmp addr
RSKP PROC NEAR
pop bp
add bp,3
push bp
; ret
RSKP ENDP
R PROC NEAR
ret
R ENDP
code ends
END